const ONEDAYMillSECOND = 1000 * 60 * 60 * 24;
const ONEHOURMillSECOND = 1000 * 60 * 60;
const ONEMINUTEMillSECOND = 1000 * 60;

const HOURS_24 = ONEDAYMillSECOND;

/**
 * @return Date对象
 */
function getTime(str) {
  let time;
  if (str) {
    time = new Date(str);
  } else {
    time = new Date();
  }
  return time;
}

/**
 * @return string 字符串
 */
function dateFormat(date, format) {
  //Date对象
  let m = new Array(
    '一月',
    '二月',
    '三月',
    '四月',
    '五月',
    '六月',
    '七月',
    '八月',
    '九月',
    '十月',
    '十一月',
    '十二月',
  );
  let o = {
    'M+': date.getMonth() + 1, //月份
    'd+': date.getDate(), //日
    'h+': date.getHours(), //小时
    'm+': date.getMinutes(), //分
    's+': date.getSeconds(), //秒
    'q+': Math.floor((date.getMonth() + 3) / 3), //季度
    S: date.getMilliseconds(), //毫秒
  };
  if (/(y+)/.test(format))
    format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
  for (var k in o)
    if (new RegExp('(' + k + ')').test(format))
      format = format.replace(
        RegExp.$1,
        RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length),
      );
  if (/(EN)/.test(format)) format = format.replace('EN', m[date.getMonth()]);
  return format;
}

/**
 *
 * @param {*} time String "yyyy-MM"的形式,不传获取当月开始时间
 * @return 月份开始时间毫秒数 0点0分0秒
 */
function getMonthStart(time = Date.now()) {
  if (checkTimeType(time)) time = dateFormat(getTime(time), 'yyyy-MM');
  return getTime(time) / 1 + 1000 * 60 * getTime().getTimezoneOffset();
}

/**
 *
 * @param {*} time String "yyyy-MM"的形式,不传获取当月结束时间
 * @return 月份结束时间毫秒数 23点59分59秒
 */
function getMonthEnd(time = Date.now()) {
  if (checkTimeType(time)) time = dateFormat(getTime(time), 'yyyy-MM');
  let year = time.split('-')[0];
  let month = getTime(time).getMonth() + 2; //获取下个月的月份
  if (month == 13) {
    year = year / 1 + 1;
    month = 1;
  }
  month = month < 10 ? '0' + month : month;
  return getMonthStart(year + '-' + month) - 1;
}

function getDayStart(time = Date.now()) {
  if (checkTimeType(time)) time = dateFormat(getTime(time), 'yyyy-MM-dd');
  return getTime(time) / 1 + 1000 * 60 * getTime().getTimezoneOffset();
}

function getDayEnd(time = Date.now()) {
  if (checkTimeType(time)) time = dateFormat(getTime(time), 'yyyy-MM-dd');
  return getDayStart(time) - 1 + ONEDAYMillSECOND;
}

/**
 * @return timeStr 时间戳
 */
function getPrevDay(day = 1, time) {
  if (!checkTimeType(time)) time = undefined;
  return getTime(time) / 1 - ONEDAYMillSECOND * day;
}

/**
 * @return timeStr 时间戳
 */
function getNextDay(day = 1, time) {
  if (!checkTimeType(time)) time = undefined;
  return getTime(time) / 1 + ONEDAYMillSECOND * day;
}

/**
 * @return  [second,minute,minuteInhour,hour]数组
 */
function durationTransform(duration) {
  const timeDuration = Math.round(duration);
  const second = timeDuration % 60;
  const minute = ~~(timeDuration / 60);
  const minuteInhour = minute % 60;
  const hour = ~~(minute / 60);
  return [second, minute, minuteInhour, hour];
}

/**
 * @return  {day, hour, minute, second}
 */
function durationTimeTransform(duration) {
  const timeDuration = Math.round(duration);
  const day = ~~(timeDuration / ONEDAYMillSECOND);
  const hour = ~~((timeDuration - day * ONEDAYMillSECOND) / ONEHOURMillSECOND);
  const minute = ~~(
    (timeDuration - day * ONEDAYMillSECOND - hour * ONEHOURMillSECOND) /
    ONEMINUTEMillSECOND
  );
  const second = ~~(
    (timeDuration -
      day * ONEDAYMillSECOND -
      hour * ONEHOURMillSECOND -
      minute * ONEMINUTEMillSECOND) /
    1000
  );
  return { day, hour, minute, second };
}

/**
 * @return  5天6时32分10秒
 */
function durationTimeFormat(duration, withSecond = false, txtBefore = '', txtAfter = '') {
  const { day, hour, minute, second } = durationTimeTransform(duration);
  let timeStr = day + '天' + hour + '时' + minute + '分';
  if (withSecond) {
    timeStr += second + '秒';
  }
  return txtBefore + timeStr + txtAfter;
}

function dateDifferentYear(date, format = 'yyyy-MM-dd hh:mm') {
  const currentYear = dateFormat(getTime(), 'yyyy') / 1;
  const dateYear = date.getFullYear();
  if (currentYear == dateYear && /(y+)/.test(format)) {
    format = format.replace(RegExp.$1 + '-', '');
  }
  return dateFormat(getTime(date), format);
}

function getType(param) {
  return Object.prototype.toString.call(param);
}

function checkTimeType(param) {
  const paramType = getType(param);
  return paramType === '[object Number]' || paramType === '[object Date]';
}

function countdownTransform(duration, padLength, padStr = '0') {
  let rest = duration;

  const HOURS_1 = 1 * 60 * 60 * 1000;
  const MINUTE_1 = 1 * 60 * 1000;
  const SECOND_1 = 1 * 1000;

  const hour = Math.floor(duration / HOURS_1);
  rest -= hour * HOURS_1;

  const minute = Math.floor(rest / MINUTE_1);
  rest -= minute * MINUTE_1;

  const second = Math.floor(rest / SECOND_1);

  if (padLength === undefined) {
    return [hour, minute, second, rest];
  }

  return [hour, minute, second, rest].map((item) => {
    return `${item}`.padStart(padLength, padStr);
  });
}

export {
  getTime,
  dateFormat,
  getMonthStart,
  getMonthEnd,
  getDayStart,
  getDayEnd,
  durationTransform,
  durationTimeTransform,
  durationTimeFormat,
  getPrevDay,
  getNextDay,
  dateDifferentYear,
  countdownTransform,
  HOURS_24,
};
